module cpu_emulated(
        input           i_wb_clk,
        input           i_wb_rst,
        input           i_wb_ack,
        input   [31:0]  i_wb_dat,
        output          o_wb_cyc,
        output          o_wb_stb,
        output          o_wb_we,
        output  [31:2]  o_wb_adr,
        output  [ 3:0]  o_wb_sel,
        output  [31:0]  o_wb_dat,
        output  [ 2:0]  o_wb_cti,
        output  [ 1:0]  o_wb_bte,
        input           i_irq,
        input           i_fiq,
        output          o_read_instr,
        output  [31:2]  o_pc,
        input   [31:0]  i_instr
);

reg        wb_cyc_o;
reg        wb_stb_o;
reg        wb_we_o;
reg [31:0] wb_adr_o;
reg [ 3:0] wb_sel_o;
reg [31:0] wb_dat_o;

reg        read_instr;
reg [31:0] pc;

assign o_wb_cyc = wb_cyc_o;
assign o_wb_stb = wb_stb_o;
assign o_wb_we  = wb_we_o;
assign o_wb_adr = wb_adr_o[31:2];
assign o_wb_sel = wb_sel_o;
assign o_wb_dat = wb_dat_o;

assign o_read_instr = read_instr;
assign o_pc = pc[31:2];

assign o_wb_cti = 3'b0;
assign o_wb_bte = 2'b0;

initial $emu_init;

reg [1:0] a;
reg instr_ack;

always @(posedge i_wb_clk) begin
        if (i_wb_rst) begin
                a <= 2'b10;
                instr_ack <= 1'b0;
        end else begin
                if (read_instr & ~instr_ack) begin
                        a <= {1'b0, a[1]};
                        instr_ack <= a[0];
                end else begin
                        a <= 2'b10;
                        instr_ack <= 1'b0;
                end
        end
end

reg dbg;

wire [ 95:0] emu_in;
reg  [127:0] emu_out;

wire        irden;
wire        fin;
wire        drden;
wire        dwren;
wire [31:0] dadr;
wire [ 3:0] dsel;
wire [31:0] ddat;
wire [31:0] iadr;

assign irden = emu_out[0];
assign fin   = emu_out[1];
assign drden = emu_out[2];
assign dwren = emu_out[3];
assign dsel  = emu_out[7:4];
assign iadr  = emu_out[63:32];
assign dadr  = emu_out[95:64];
assign ddat  = emu_out[127:96];

assign emu_in = {i_wb_dat, i_instr, 30'b0, i_wb_ack, instr_ack};

always @(negedge i_wb_clk) begin
        emu_out = $emu_run(emu_in);
end

always @(posedge i_wb_clk) begin
        if (fin) $finish;
        wb_cyc_o <= drden | dwren;
        wb_stb_o <= drden | dwren;
        wb_we_o  <= dwren;
        wb_adr_o <= dadr;
        wb_sel_o <= dsel;
        wb_dat_o <= ddat;
        read_instr <= irden;
        pc <= iadr;
end

endmodule
